//
// GPSMapEdit
// (c) Konstantin Galichsky (kg@geopainting.com), 2006-2007
// Garmin and MapSource are registered trademarks or trademarks of Garmin Ltd. or one of its subsidiaries.
//
// Helpers for MapSource-specific formats.
//

# include "StdAfx.h"
# include "MapSourceHelpers.h"
# include "Globals.h"

static
bool _IsSpacesOnly (const TCHAR * _str) {
	while (* _str != _T ('\0')) {
		if (* _str != _T (' '))
			return false;
		_str = ::CharNext (_str);
	}

	return true;
}

static
bool _StrEqualMS (const TCHAR * _str1, const TCHAR * _str2) {
	const TCHAR * p1 = _str1;
	const TCHAR * p2 = _str2;
	while (* p1 != _T ('\0') && * p2 != _T ('\0')) {
		if (::CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE, p1, 1, p2, 1) != CSTR_EQUAL)
			break;
		p1 = ::CharNext (p1);
		p2 = ::CharNext (p2);
	}

	if (* p1 == _T ('\0') && * p2 == _T ('\0'))
		return true;
	if (* p1 != _T ('\0') && * p2 != _T ('\0')) {
		assert (* p1 != * p2);
		return false;
	}

	// Ignore final spaces.
	if (* p1 != _T ('\0'))
		return _IsSpacesOnly (p1);
	else
		return _IsSpacesOnly (p2);
}

bool LessWptName::operator () (const string_t & _str1, const string_t & _str2) const {
	const bool bEqual = _StrEqualMS (_str1.c_str (), _str2.c_str ());
	if (bEqual)
		return false;
	else
		return _str1 < _str2;
}

//////////////////////////////////////////////////////////////////

void GenerateUniqueNameForMapSource (const string_t & _strName0, names_t & _names, string_t & _strName) {
	const string_t & strName0 = _strName0.empty () ? "NONAME" : _strName0;
	const names_t::iterator i = _names.find (strName0);
	if (i == _names.end ()) {
		_strName = strName0;
		_names [strName0] = 1;
	} else {
		do {
			const size_t cOrdinal = ++ (i->second);

			_strName = strName0;
			char strSuffix [10];
			::sprintf (strSuffix, " (%d)", cOrdinal);
			_strName.append (strSuffix);
		} while (_names.find (_strName) != _names.end ());
	}

	if (! _strName.empty ()) {
		const size_t cLen = ::strlen (_strName.c_str ());
		if (cLen < _strName.size ()) {
			// NOTE: '\0' inside string is not savable to MapSource MPS/GDB; let's trim it.
			string_t strTmp;
			strTmp.swap (_strName);
			_strName.assign (strTmp.c_str (), cLen);
		}
	}
}

////////////////////////////////////////////////////////

# pragma const_seg (".text")

const COLORREF g_GarminTrackColors [] = {
	c_colGray, // for unknown
	c_colBlack,
	c_colDkRed,
	c_colDkGreen,
	c_colDkYellow,
	c_colDkBlue,
	c_colDkMagenta,
	c_colDkCyan,
	c_colLtGray,
	c_colDkGray,
	c_colRed,
	c_colGreen,
	c_colYellow,
	c_colBlue,
	c_colMagenta,
	c_colCyan,
	c_colWhite
};

const size_t c_cGarminTrackColors = sizeof (g_GarminTrackColors)/sizeof (g_GarminTrackColors [0]);

# pragma const_seg ()

size_t FindNearestGarminTrackColor (COLORREF _col) {
	size_t cBest = 0;
	long lMinDiff = 256*3;
	for (size_t c = 1; c < c_cGarminTrackColors; ++ c) {
		const long lDiff =
			::labs (GetRValue (g_GarminTrackColors [c]) - GetRValue (_col)) + 
			::labs (GetGValue (g_GarminTrackColors [c]) - GetGValue (_col)) + 
			::labs (GetBValue (g_GarminTrackColors [c]) - GetBValue (_col));

		if (lMinDiff > lDiff) {
			lMinDiff = lDiff;
			cBest = c;
		}
	}

	return cBest;
}

////////////////////////////////////////////////////////////

struct t2t_t {
	WORD wWaypointType;
	WORD wPOIType;
};

# pragma const_seg (".text")

static
const t2t_t g_t2t [] = {
	{0x00, 0x2f09}, // Anchor
	{0x01, 0x2c05}, // Bell
	{0x02, 0},      // Green diamond
	{0x03, 0},      // Red diamond
	{0x04, 0x5c00}, // Diver down flag 1
	{0x05, 0x5c00}, // Diver down flag 2
	{0x06, 0x2f06}, // Bank
	{0x07, 0x4100}, // Fishing area
	{0x08, 0x4400}, // Gas station
	{0x09, 0x1601}, // Horn
	{0x0a, 0x6402}, // Residence -> building
	{0x0b, 0x4500}, // Restaraunt
	{0x0c, 0},      // Light
	{0x0d, 0x2d02}, // Bar
	{0x0e, 0x5700}, // Skull and crossbones -> danger area
	{0x0f, 0x5d00}, // Green square

	{0x10, 0},      // Red square
	{0x11, 0x1606}, // White buoy 
	{0x12, 0},      // Waypoint
	{0x13, 0x1c01}, // Ship wreck
	{0x14, 0},      // Man overboard
	{0x15, 0x1612}, // Navaid (amber)
	{0x16, 0x160a}, // Navaid (black)
	{0x17, 0x1615}, // Navaid (blue)
	{0x18, 0x1611}, // Navaid (green)
	{0x19, 0x1616}, // Navaid (green/red)
	{0x1a, 0x1616}, // Navaid (green/white)
	{0x1b, 0x1613}, // Navaid (orange)
	{0x1c, 0x1610}, // Navaid (red)
	{0x1d, 0x1616}, // Navaid (red/green)
	{0x1e, 0x1616}, // Navaid (red/white)
	{0x1f, 0x1614}, // Navaid (violet)
	{0x20, 0x160f}, // Navaid (white)

	{0x21, 0x1616}, // Navaid (white/green)
	{0x22, 0x1616}, // Navaid (white/red)
	{0x23, 0},      // White dot
	{0x24, 0x1602}, // Radio beacon
	{0x25, 0x4700}, // Boat ramp
	{0x26, 0x4800}, // Campground
	{0x27, 0x2f0c}, // Restroom
	{0x28, 0x4f00}, // Shower
	{0x29, 0x6414}, // Drinking water
	{0x2a, 0x5100}, // Telephone
	{0x2b, 0x4b00}, // Medical facility -> First aid station
	{0x2c, 0x4c00}, // Information
	{0x2d, 0x2f0b}, // Parking area -> parking
	{0x2e, 0x640e}, // Park
	{0x2f, 0x4a00}, // Picnic area

	{0x30, 0x5200}, // Scenic area
	{0x31, 0x5300}, // Skiing area
	{0x32, 0x2d09}, // Swimming area -> swimming
	{0x33, 0x5500}, // Dam
	{0x34, 0x5600}, // Controlled area
	{0x35, 0x5700}, // Danger area
	{0x36, 0x5800}, // Restricted area
	{0x37, 0x2c08}, // Ball park
	{0x38, 0x2f0b}, // Car -> parking
	{0x39, 0},      // Hunting area
	{0x3a, 0x2e04}, // Shopping area
	{0x3b, 0x2b00}, // Lodging
	{0x3c, 0x640c}, // Mine
	{0x3d, 0x6412}, // Trail head
	{0x3e, 0x2f16}, // Truck stop
	{0x3f, 0x2000}, // Exit

	{0x40, 0},      // Flag
	{0x41, 0},      // Circle with X
	{0x42, 0x640a}, // Mile marker -> Locale 
	{0x43, 0},      // Trackback point 
	{0x44, 0x2d05}, // Golf course
	{0x45, 0x0900}, // City small
	{0x46, 0x0700}, // City medium
	{0x47, 0x0300}, // City large
	{0x48, 0x0100}, // City capitol -> City1 
	{0x49, 0x2c01}, // Amusement park
	{0x4a, 0x2d07}, // Bowling
	{0x4b, 0x2f02}, // Car rental
	{0x4c, 0x2f03}, // Car repair -> auto repair
	{0x4d, 0x2a07}, // Fast food
	{0x4e, 0x2d0a}, // Fitness center
	{0x4f, 0x2d03}, // Movie theater

	{0x50, 0x2c02}, // Museum -> museum/history
	{0x51, 0x2e05}, // Pharmacy
	{0x52, 0x2a0a}, // Pizza -> Fast food (pizza)
	{0x53, 0x2f05}, // Post office
	{0x54, 0x2b03}, // RV park
	{0x55, 0x2c05}, // School
	{0x56, 0x2c08}, // Stadium
	{0x57, 0x2e01}, // Department store
	{0x58, 0x2c07}, // Zoo
	{0x59, 0x2e06}, // Convenience store
	{0x5a, 0x2d01}, // Live theatre
	{0x5b, 0x2400}, // Scales -> Exit (weight station)
	{0x5c, 0x2500}, // Tool booth -> exit (toll booth)
	{0x5d, 0x6401}, // Bridge
	{0x5e, 0x6402}, // Building
	{0x5f, 0x6403}, // Cemetery

	{0x60, 0x6404}, // Church
	{0x61, 0x6405}, // Civil
	{0x62, 0x6406}, // Crossing
	{0x63, 0x6415}, // Ghost town
	{0x64, 0x6409}, // Levee
	{0x65, 0x640b}, // Military
	{0x66, 0x640d}, // Oil field
	{0x67, 0x6413}, // Tunnel
	{0x68, 0x6604}, // Beach
	{0x69, 0x660a}, // Forest
	{0x6a, 0x6616}, // Summit
	{0x6b, 0x5900}, // Airport
	{0x6c, 0x5904}, // Heliport
	{0x6d, 0},      // Private field
	{0x6e, 0},      // Soft field 
	{0x6f, 0x6411}, // Tall tower

	{0x70, 0x6411}, // Short tower
	{0x71, 0x5900}, // Glider area -> airport
	{0x72, 0},      // Ultralight area 
	{0x73, 0},      // Parachute area
	{0x74, 0x5900}, // Seaplane base 
	{0x75, 0},      // Geocache 
	{0x76, 0},      // Geocache found
	{0x77, 0},      // Contact (afro)
	{0x78, 0},      // Contact (alien)
	{0x79, 0},      // Contact (ball cap)
	{0x7a, 0},      // Contact (big ears)
	{0x7b, 0},      // Contact (biker)
	{0x7c, 0},      // Contact (bug)
	{0x7d, 0},      // Contact (cat)
	{0x7e, 0},      // Contact (dog)
	{0x7f, 0},      // Contact (dread locks)

	{0x80, 0},      // Contact (female 1)
	{0x81, 0},      // Contact (female 2)
	{0x82, 0},      // Contact (female 3)
	{0x83, 0},      // Contact (goatee)
	{0x84, 0},      // Contact (kung-fu)
	{0x85, 0},      // Contact (pig)
	{0x86, 0},      // Contact (pirate)
	{0x87, 0},      // Contact (ranger)
	{0x88, 0},      // Contact (smiley)
	{0x89, 0},      // Contact (spike)
	{0x8a, 0},      // Contact (sumo)
	{0x8b, 0},      // Water gidrant
	{0x8c, 0},      // Flag Red
	{0x8d, 0},      // Flag Blue
	{0x8e, 0},      // Flag Green
	{0x8f, 0},      // Pin Red

	{0x90, 0},      // Pin Blue
	{0x91, 0},      // Pin Green
	{0x92, 0},      // Block Red
	{0x93, 0},      // Block Blue
	{0x94, 0},      // Block Green
	{0x95, 0},      // Bike Trail
	{0x96, 0x4100}, // Fishing Hot Spot Facility
	{0x97, 0x3001}, // Police Station
	{0x98, 0x2d06}, // Ski Resort
	{0x99, 0x2d08}, // Ice Skating
	{0x9a, 0x2f0a}, // Wrecker -> wrecker service
	{0x9b, 0},      // Anchor Prohibited
	{0x9c, 0},      // Beacon
	{0x9d, 0},      // Coast Guard
	{0x9e, 0x1c09}, // Reef
	{0x9f, 0},      // Weed Bed

	{160, 0},      // Dropoff
	{161, 0},      // Dock
	{162, 0x4300}, // Marina
	{163, 0},      // Bait and Tackle
	{164, 0},      // Stump

	{165, 0},      // Circle Red
	{166, 0},      // Circle Green
	{167, 0},      // Circle Blue
	{168, 0},      // Diamond Blue
	{169, 0},      // Oval Red
	{170, 0},      // Oval Green
	{171, 0},      // Oval Blue
	{172, 0},      // Rectangle Red
	{173, 0},      // Rectangle Green
	{174, 0},      // Rectangle Blue
	{175, 0},      // Square Blue

	{176, 0},      // Letter_A_Red},
	{177, 0},      // Letter_A_Green},
	{178, 0},      // Letter_A_Blue},
	{179, 0},      // Letter_B_Red},
	{180, 0},      // Letter_B_Green},
	{181, 0},      // Letter_B_Blue},
	{182, 0},      // Letter_C_Red},
	{183, 0},      // Letter_C_Green},
	{184, 0},      // Letter_C_Blue},
	{185, 0},      // Letter_D_Red},
	{186, 0},      // Letter_D_Green},
	{187, 0},      // Letter_D_Blue},

	{188, 0},      // Number_0_Red},
	{189, 0},      // Number_0_Green},
	{190, 0},      // Number_0_Blue},
	{191, 0},      // Number_1_Red},
	{192, 0},      // Number_1_Green},
	{193, 0},      // Number_1_Blue},
	{194, 0},      // Number_2_Red},
	{195, 0},      // Number_2_Green},
	{196, 0},      // Number_2_Blue},
	{197, 0},      // Number_3_Red},
	{198, 0},      // Number_3_Green},
	{199, 0},      // Number_3_Blue},
	{200, 0},      // Number_4_Red},
	{201, 0},      // Number_4_Green},
	{202, 0},      // Number_4_Blue},
	{203, 0},      // Number_5_Red},
	{204, 0},      // Number_5_Green},
	{205, 0},      // Number_5_Blue},
	{206, 0},      // Number_6_Red},
	{207, 0},      // Number_6_Green},
	{208, 0},      // Number_6_Blue},
	{209, 0},      // Number_7_Red},
	{210, 0},      // Number_7_Green},
	{211, 0},      // Number_7_Blue},
	{212, 0},      // Number_8_Red},
	{213, 0},      // Number_8_Green},
	{214, 0},      // Number_8_Blue},
	{215, 0},      // Number_9_Red},
	{216, 0},      // Number_9_Green},
	{217, 0},      // Number_9_Blue},

	{218, 0},      // Triangle_Blue},
	{219, 0},      // Triangle_Green},
	{220, 0},      // Triangle_Red}

	// MapSource 6.12
	{0xdd, 0},      // Contact (blonde)
	{0xde, 0},      // Contact (clown)
	{0xdf, 0},      // Contact (glasses)
	{0xe0, 0},      // Contact (panda)

	{0xe1, 0},      // Multi-cache   (outdoor)
	{0xe2, 0},      // Letterbox cache (outdoor)
	{0xe3, 0},      // Puzzle cache  (outdoor)

	{0xe4, 0x2c03}, // Library       (civil)
	{0xe5, 0x2f08}, // Ground transportation (transportation)
	{0xe6, 0x3003}, // City hall     (civil)
	{0xe7, 0x2c0a}, // Winery        (business)
	{0xe8, 0},      // ATV           (outdoor)
	{0xe9, 0},      // Big game      (hunting)
	{0xea, 0},      // Blind         (hunting)
	{0xeb, 0},      // Blood trail   (hunting)
	{0xec, 0},      // Cover         (hunting)
	{0xed, 0},      // Covey         (hunting)
	{0xee, 0},      // Food source   (hunting)
	{0xef, 0},      // Furbearer     (hunting)
	{0xf0, 0x2b00}, // Lodge         (outdoor)
	{0xf1, 0},      // Small game    (hunting)
	{0xf2, 0},      // Animal tracks (hunting)
	{0xf3, 0},      // Treed quarry  (hunting)
	{0xf4, 0},      // Tree stand    (hunting)
	{0xf5, 0x2f16}, // Truck         (outdoor)
	{0xf6, 0},      // Upland game   (hunting)
	{0xf7, 0},      // Waterfowl     (hunting)
	{0xf8, 0},      // Water source  (hunting)

	// 0x1f4 (500 dec) - custom waypoint 1
};

const size_t g_cT2TSize = sizeof (g_t2t)/sizeof (g_t2t [0]);

# pragma const_seg ()

WORD GarminWPT2POIType (WORD _wType) {
	size_t a = 1, b = g_cT2TSize - 1;
	while (true) {
		const WORD wA = g_t2t [a].wWaypointType;
		if (wA == _wType)
			return g_t2t [a].wPOIType;

		const WORD wB = g_t2t [b].wWaypointType;
		if (wB == _wType)
			return g_t2t [b].wPOIType;

		if (b - a <= 1)
			return 0;

		const size_t m = (a + b)/2;

		const WORD wM = g_t2t [m].wWaypointType;
		if (wM < _wType)
			a = m;
		else
			b = m;
	}
}

